package downloader

import (
	"context"
	"fmt"
	"image_demo/internal/constants"
	"io"
	"math/rand"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

// MediaType 表示媒体类型
type MediaType string

const (
	MediaTypeImage MediaType = "image"
	MediaTypeVideo MediaType = "video"
)

// Downloader 处理图片和视频下载的统一下载器
type Downloader struct {
	httpClient    *http.Client
	converter     *WebPConverter
	convertToWebP bool
}

// NewDownloader 创建新的统一下载器
func NewDownloader(convertToWebP bool) *Downloader {
	return &Downloader{
		httpClient:    createHttpClient(),
		converter:     NewWebPConverter(constants.WebPLossless, constants.WebPQuality),
		convertToWebP: convertToWebP,
	}
}

// 创建带防限流配置的HTTP客户端
func createHttpClient() *http.Client {
	return &http.Client{
		Timeout: constants.HTTPTimeout,
		Transport: &http.Transport{
			MaxIdleConns:        constants.MaxIdleConns,
			IdleConnTimeout:     constants.IdleConnTimeout,
			DisableCompression:  true,
			DisableKeepAlives:   false,
			MaxIdleConnsPerHost: constants.MaxIdleConnsPerHost,
		},
	}
}

// 获取随机User-Agent
func getRandomUserAgent() string {
	return constants.UserAgents[rand.Intn(len(constants.UserAgents))]
}

// DownloadMedia 下载媒体文件（图片或视频）
func (d *Downloader) DownloadMedia(ctx context.Context, mediaURL, outputDir string, mediaType MediaType) error {
	req, err := http.NewRequestWithContext(ctx, "GET", mediaURL, nil)
	if err != nil {
		return fmt.Errorf("创建媒体请求失败: %v", err)
	}

	// 设置请求头
	req.Header.Set(constants.UserAgentHeader, getRandomUserAgent())
	req.Header.Set(constants.AcceptLanguageHeader, constants.DefaultAcceptLanguage)
	req.Header.Set(constants.RefererHeader, constants.DefaultReferer)

	// 根据媒体类型设置不同的Accept头
	switch mediaType {
	case MediaTypeImage:
		req.Header.Set(constants.AcceptHeader, constants.ImageAccept)
	case MediaTypeVideo:
		req.Header.Set(constants.AcceptHeader, "*/*") // 视频下载接受所有类型
	}

	resp, err := d.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("下载媒体失败: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != constants.HTTPStatusOK {
		return fmt.Errorf("媒体下载失败，状态码: %d", resp.StatusCode)
	}

	// 根据媒体类型处理响应
	switch mediaType {
	case MediaTypeImage:
		return d.handleImageDownload(resp, mediaURL, outputDir)
	case MediaTypeVideo:
		return d.handleVideoDownload(resp, mediaURL, outputDir)
	default:
		return fmt.Errorf("不支持的媒体类型: %s", mediaType)
	}
}

// handleImageDownload 处理图片下载和转换
func (d *Downloader) handleImageDownload(resp *http.Response, imageURL, outputDir string) error {
	imgData, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取图片数据失败: %v", err)
	}

	outputPath := generateImageOutputPath(imageURL, outputDir, d.convertToWebP)

	if d.convertToWebP {
		// 转换为WebP格式
		if err := d.converter.ConvertToWebP(imgData, outputPath); err != nil {
			return fmt.Errorf("图片转换失败: %v", err)
		}
		fmt.Printf("成功下载并转换图片: %s\n", outputPath)
	} else {
		// 保存原始格式
		dir := filepath.Dir(outputPath)
		if err := os.MkdirAll(dir, constants.DirPermission); err != nil {
			return fmt.Errorf("创建目录失败: %v", err)
		}

		outputFile, err := os.Create(outputPath)
		if err != nil {
			return fmt.Errorf("创建输出文件失败: %v", err)
		}
		defer outputFile.Close()

		if _, err := outputFile.Write(imgData); err != nil {
			return fmt.Errorf("保存图片文件失败: %v", err)
		}
		fmt.Printf("成功下载图片: %s\n", outputPath)
	}

	return nil
}

// handleVideoDownload 处理视频下载
func (d *Downloader) handleVideoDownload(resp *http.Response, videoURL, outputDir string) error {
	// 获取视频文件扩展名
	contentType := resp.Header.Get("Content-Type")
	fileExt := getVideoExtension(contentType, videoURL)

	outputPath := generateVideoOutputPath(videoURL, outputDir, fileExt)

	// 确保输出目录存在
	dir := filepath.Dir(outputPath)
	if err := os.MkdirAll(dir, constants.DirPermission); err != nil {
		return fmt.Errorf("创建目录失败: %v", err)
	}

	// 创建输出文件
	outputFile, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("创建输出文件失败: %v", err)
	}
	defer outputFile.Close()

	// 复制视频数据到文件
	if _, err := io.Copy(outputFile, resp.Body); err != nil {
		return fmt.Errorf("保存视频文件失败: %v", err)
	}

	fmt.Printf("成功下载视频: %s\n", outputPath)
	return nil
}

// getVideoExtension 根据Content-Type和URL获取视频文件扩展名
func getVideoExtension(contentType, videoURL string) string {
	// 优先根据Content-Type判断
	switch contentType {
	case "video/mp4":
		return ".mp4"
	case "video/webm":
		return ".webm"
	case "video/avi":
		return ".avi"
	case "video/mov":
		return ".mov"
	case "video/mkv":
		return ".mkv"
	default:
		// 如果Content-Type未知，从URL中提取扩展名
		ext := filepath.Ext(videoURL)
		if ext != "" {
			return ext
		}
		// 默认使用mp4格式
		return ".mp4"
	}
}

// GenerateImageOutputPath 生成图片输出文件路径
func GenerateImageOutputPath(imageURL, outputDir string, convertToWebP bool) string {
	baseName := filepath.Base(imageURL)
	ext := filepath.Ext(baseName)
	nameWithoutExt := strings.TrimSuffix(baseName, ext)

	if convertToWebP {
		return filepath.Join(outputDir, nameWithoutExt+".webp")
	}

	// 保持原始扩展名
	return filepath.Join(outputDir, baseName)
}

// GenerateVideoOutputPath 生成视频输出文件路径
func GenerateVideoOutputPath(videoURL, outputDir, fileExt string) string {
	baseName := filepath.Base(videoURL)
	originalExt := filepath.Ext(baseName)
	nameWithoutExt := strings.TrimSuffix(baseName, originalExt)

	// 如果URL中已经有扩展名，使用URL中的扩展名
	if originalExt != "" && originalExt != fileExt {
		// 如果扩展名不同，使用新的扩展名
		return filepath.Join(outputDir, nameWithoutExt+fileExt)
	}

	return filepath.Join(outputDir, baseName)
}

// 内部使用的generateImageOutputPath函数
func generateImageOutputPath(imageURL, outputDir string, convertToWebP bool) string {
	return GenerateImageOutputPath(imageURL, outputDir, convertToWebP)
}

// 内部使用的generateVideoOutputPath函数
func generateVideoOutputPath(videoURL, outputDir, fileExt string) string {
	return GenerateVideoOutputPath(videoURL, outputDir, fileExt)
}
